package belf.migrate.engine.ddl.function.oracle;

import belf.migrate.core.jdbc.FunctionModel;
import belf.migrate.core.jdbc.TypeModel;
import belf.migrate.core.util.StringTool;
import belf.migrate.engine.ddl.BaseDDLConvert;
import belf.migrate.plugin.oracle.antlr.PlSqlParser;
import belf.migrate.plugin.oracle.antlr.PlSqlParserBaseVisitor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 基于antlr解析的Oracle函数的语法树，重构sql语句的辅助类
 */
public class OracleFunctionVistor extends PlSqlParserBaseVisitor<String> {
    //以下5个参数为构造参数
    private BaseDDLConvert ddlConvert;
    private String quote = "\"";
    private String schema;
    private Map<String, FunctionModel> funcMapping;
    private Map<String, TypeModel> typeMapping;

    //函数名称
    private String functionName;
    //参数列表
    private List<PlSqlParser.ParameterContext> parameters;
    //返回值
    private String returnType;
    // MySql函数定义里，参数申明在BEGIN..END之间，在达梦的函数定义里参数申明需要提到BEGIN之前
    private List<PlSqlParser.Declare_specContext> variables;
    // BEGIN...END之间的函数定义语句
    private List<PlSqlParser.StatementContext> procedureSqls;

    public OracleFunctionVistor(BaseDDLConvert ddlConvert,
                                String quote,
                                String schema,
                                Map<String, FunctionModel> funcMapping,
                                Map<String, TypeModel> typeMapping) {
        this.ddlConvert = ddlConvert;
        this.quote = quote;
        this.schema = schema;
        this.funcMapping = funcMapping;
        this.typeMapping = typeMapping;

        parameters = new ArrayList<>();
        variables = new ArrayList<>();
        procedureSqls = new ArrayList<>();
    }

    @Override
    public String visitCreate_function_body(PlSqlParser.Create_function_bodyContext ctx) {
        //函数名称，需要加上schema，并加上引号
        functionName = ctx.function_name().getText().trim();
        if (functionName.indexOf('.') == -1) {
            functionName = StringTool.addQuote(schema, quote) + "." + StringTool.addQuote(functionName, quote);
        }
        //函数参数
        parameters.addAll(ctx.parameter());
        //函数返回值，需要做类型替换
        returnType = ctx.type_spec().datatype().getText().trim();
        if (typeMapping.containsKey(returnType)) {
            returnType = typeMapping.get(returnType).getTo();
        }

        //BEGIN...END中间的函数定义语句列表
        procedureSqls.addAll(ctx.body().seq_of_statements().statement());
        return visitChildren(ctx);
    }

    @Override
    public String visitDeclare_spec(PlSqlParser.Declare_specContext ctx) {
        if ((ctx.variable_declaration() != null &&
                ctx.variable_declaration().identifier() != null &&
                !ctx.variable_declaration().identifier().getText().equalsIgnoreCase("SET"))
                || ctx.type_declaration() != null) {
            variables.add(ctx);  //找到定义的变量，可能在BEGIN之前或之后
        }
        return visitChildren(ctx);
    }

    public String getFunctionName() {
        return functionName;
    }

    public List<PlSqlParser.ParameterContext> getParameters() {
        return parameters;
    }

    public String getReturnType() {
        return returnType;
    }

    public List<PlSqlParser.Declare_specContext> getVariables() {
        return variables;
    }

    public List<PlSqlParser.StatementContext> getProcedureSqls() {
        return procedureSqls;
    }
}
